package com.longtxt.powerband.core

import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanSettings
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import java.util.concurrent.atomic.AtomicBoolean

class BleScanner(
    private val mBluetoothAdapter: BluetoothAdapter,
    private val leScanCallback: ScanCallback,
    private val stopListener: () -> Unit
) {


    private val mHandler = Handler(Looper.getMainLooper())
    private var isScanning = AtomicBoolean(false)

    @SuppressLint("MissingPermission")
    fun startScan(timeOut: Int = 4, filters: List<ScanFilter> = emptyList()) {
        if (isScanning.get()) {
            Log.e(TAG, "Already scanning")
            return
        }
        isScanning.set(true)
        mHandler.postDelayed({
            if (isScanning.get()) {
                isScanning.set(false)
                stopScan()
            }
        }, timeOut * 1000L)
        val scanSettingsBuild = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                .setReportDelay(0L)
                .setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED)
        } else {
            ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
        }
        scanSettingsBuild.apply {
            setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
            setNumOfMatches(ScanSettings.MATCH_NUM_ONE_ADVERTISEMENT)
        }
        mBluetoothAdapter.bluetoothLeScanner.startScan(
            filters,
            scanSettingsBuild.build(),
            leScanCallback
        )
    }

    @SuppressLint("MissingPermission")
    fun stopScan() {
        isScanning.set(false)
        if (mBluetoothAdapter.bluetoothLeScanner != null) {
            mBluetoothAdapter.bluetoothLeScanner.stopScan(leScanCallback)
            Log.i(TAG, "Scanning stopped")
        }
        stopListener.invoke()
    }

    companion object {
        const val TAG = "BleScanner"
    }
}